// any
// unknown
// never

// never 用来定义函数的
// 两种：
// 1、函数死循环，没有结束
// 2、函数抛出错误，不能执行完

// void
// 表示函数的返回值为空，即`undefined`, 函数默认返回值为`undefined`
// 但是在ts中，不能拿该函数的返回值进行判断
// 如果在声明函数的时候，定义了返回值是没有问题的，如果是先定义了函数类型，然后再去用，那么函数的void返回值限制就会出现（写了返回值是其他类型，也不会报错），但是仍然不能使用返回值去判断

// public 
// 类内部，类外部（实例对象），子类可以访问
// protected 
// 类内部，子类可以访问
// private
// 类内部可以访问 

// interface 和 type 的区别
// 相同点： interface 和 type 都可以定义对象结构，两者在许多场景是可以互换的
// 不同点： 
//   interface： 更专注定义对象和类的结构，支持合并、继承
//   type： 可以定义类型别名、联合类型、交叉类型，但是不支持继承和自动合并

// interface 和 抽象类 的区别
// 相同点： 都用于定义一个类的格式
// 不同点：
  // interface： 只能描述结构，不能有任何实现代码，一个类可以实现多个接口
// 抽象类： 既可以包含抽象方法，也可以包含具体方法，一个类只能继承一个抽象类

// 泛型： 它允许你在定义函数、类或接口时，不预先指定具体的类型，而是在使用时再指定。这样可以提高代码的灵活性和复用性。

interface aaa {
  name: String;
  age: number;
  grade: number;
  sex: number;
}

interface bbb extends Omit<aaa, 'name' | 'age'> {

}

const val: bbb = {
  grade: 1,
  sex: 1,
}


// interface Events {
//   nav: [path: string, query?: Record<string, string | number | boolean>];
//   "value - change": [value: string | number];
//   ready: [];
// }

// interface Listener<E extends keyof Events> {
//   (...args: Events[E]): void;
// }

// interface EventEmitter {
//   on<E extends keyof Events>(event: E, listener: Listener<E>): void;
//   once<E extends keyof Events>(event: E, listener: Listener<E>): void;
//   off<E extends keyof Events>(event: E, listener: Listener<E>): void;
//   emit<E extends keyof Events>(event: E,...args: Events[E]): void;
// }

// const events: EventEmitter = {
//   on(event: string, listener: Function) {},
//   once(event: string, listener: Function) {},
//   off(event: string, listener: Function) {},
//   emit(event: string,...args: any[]) {}
// };

// events.on("nav", (path, query) => {});

// events.emit("value - change", "value");
// events.emit("value - change", 123);
// events.emit("ready");